package jp.eisbahn.mgapi.auth;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import jp.eisbahn.mgapi.http.ContentType;
import jp.eisbahn.mgapi.http.HttpFetcher;
import jp.eisbahn.mgapi.http.HttpMethod;
import jp.eisbahn.mgapi.http.HttpRequest;
import jp.eisbahn.mgapi.http.HttpResponse;

import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

public class TokenProducer {
    
    public static final String MIXI_TOKEN_URL = "https://secure.mixi-platform.com/2/token";
    
    private ClientConfig clientConfig;
    
    private HttpFetcher httpFetcher;
    
    public void setClientConfig(ClientConfig clientConfig) {
        this.clientConfig = clientConfig;
    }
    
    public ClientConfig getClientConfig() {
        return clientConfig;
    }
    
    public Token issue(String authorizationCode) throws IOException {
        Map<String, Object> parameterMap = new HashMap<String, Object>();
        parameterMap.put("grant_type", "authorization_code");
        parameterMap.put("client_id", clientConfig.getClientId());
        parameterMap.put("client_secret", clientConfig.getClientSecret());
        parameterMap.put("code", authorizationCode);
        parameterMap.put("redirect_uri", clientConfig.getRedirectUri());
        return retrieveToken(parameterMap);
    }
    
    public Token refresh(Token token) throws IOException {
        Map<String, Object> parameterMap = new HashMap<String, Object>();
        parameterMap.put("grant_type", "refresh_token");
        parameterMap.put("client_id", clientConfig.getClientId());
        parameterMap.put("client_secret", clientConfig.getClientSecret());
        parameterMap.put("refresh_token", token.getRefreshToken());
        return retrieveToken(parameterMap);
    }

    private Token retrieveToken(Map<String, Object> parameterMap)
            throws IOException {
        HttpRequest request = new HttpRequest(MIXI_TOKEN_URL, parameterMap,
                HttpMethod.POST, ContentType.X_WWW_FORM_URLENCODED);
        HttpResponse response = httpFetcher.fetch(request);
        if (response.getResponseCode() == HttpServletResponse.SC_OK) {
            String responseBody = response.getResponseBody();
            Object parsed = JSONValue.parse(responseBody);
            if (parsed instanceof JSONObject) {
                JSONObject obj = (JSONObject)parsed;
                return new Token(
                        (String)obj.get("refresh_token"),
                        (String)obj.get("access_token"),
                        (Long)obj.get("expires_in"));
            } else {
                throw new IllegalStateException("Unknown response format.");
            }
        } else {
            return new Token(response.getResponseCode(), response.getResponseMessage());
        }
    }

    public void setHttpFetcher(HttpFetcher httpFetcher) {
        this.httpFetcher = httpFetcher;
    }

}
